package com.ocean.search.util;

import com.ocean.core.exception.verify.ApplicationException;
import com.ocean.core.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xcontent.XContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;

/**
 * ES工具类
 * <p>
 * 请配合Listener一起使用
 * 详见listener包
 *
 * @author zhang
 * @since 2021/6/29 15:05
 */
@Slf4j
@Component
public class SearchUtil {

    @Autowired
    private static RestHighLevelClient restHighLevelClient;

    /**
     * 手动创建索引
     *
     * @param shards       主分片
     * @param replicas     副本集
     * @param indexName    索引名称
     * @param templatePath 模板路径 resources目录下
     */
    public static void createIndex(String indexName, Integer shards, Integer replicas, String templatePath) throws Exception {
        String template = loadTemplate(templatePath);
        //查询所有索引
        GetIndexRequest getIndexRequest = new GetIndexRequest("*");
        //允许索引不存在，防止第一次连接时报错
        getIndexRequest.indicesOptions(IndicesOptions.fromOptions(true, true,
                true, true));
        GetIndexResponse getIndexResponse = restHighLevelClient.indices().get(getIndexRequest,
                RequestOptions.DEFAULT);
        String[] indices = getIndexResponse.getIndices();
        List<String> strings = Arrays.asList(indices);
        //索引不存在则创建
        if (!strings.contains(indexName)) {
            log.info("开始预备索引");
            // 创建索引
            CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);
            // 设置主分片和副本集
            createIndexRequest.settings(Settings.builder()
                    .put("index.number_of_shards", shards)
                    .put("index.number_of_replicas", replicas)
            );
            // 指定Mapping
            createIndexRequest.mapping(template, XContentType.JSON);
            // 创建索引
            CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
            log.info("索引预备完成:{}", createIndexResponse.index());
            return;
        }
        log.info("索引已存在，跳过");
    }

    /**
     * 读取mapping模板，位于resources下
     *
     * @param path 文件路径
     * @return JSON字符
     */
    public static String loadTemplate(String path) throws Exception {
        if (StringUtil.isNotNull(path)) {
            Resource resource = new ClassPathResource(path);
            InputStream is = resource.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            StringBuilder sb = new StringBuilder();
            String data;
            while ((data = br.readLine()) != null) {
                sb.append(data);
            }
            br.close();
            isr.close();
            is.close();
            if (StringUtil.isNotNull(sb.toString())) {
                return sb.toString();
            }
        }
        log.error("文件模板为空或路径错误");
        throw new ApplicationException("文件模板为空或路径错误");
    }
}
